package com.example.bigwork.service.impl;

import com.example.bigwork.dto.request.UserLoginRequest;
import com.example.bigwork.dto.request.UserRegisterRequest;
import com.example.bigwork.dto.request.UserUpdateRequest;
import com.example.bigwork.dto.response.UserResponse;
import com.example.bigwork.entity.User;
import com.example.bigwork.exception.BadRequestException;
import com.example.bigwork.exception.ResourceNotFoundException;
import com.example.bigwork.exception.UserAlreadyExistsException;
import com.example.bigwork.mapper.UserMapper;
import com.example.bigwork.service.UserService;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Service
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;
    private final PasswordEncoder passwordEncoder;

    @Autowired
    public UserServiceImpl(UserMapper userMapper, PasswordEncoder passwordEncoder) {
        this.userMapper = userMapper;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    @Transactional
    public UserResponse registerUser(UserRegisterRequest registerRequest) {
        userMapper.findByUsername(registerRequest.getUsername()).ifPresent(u -> {
            throw new UserAlreadyExistsException("Username already exists: " + registerRequest.getUsername());
        });
        userMapper.findByEmail(registerRequest.getEmail()).ifPresent(u -> {
            throw new UserAlreadyExistsException("Email already exists: " + registerRequest.getEmail());
        });

        User user = new User();
        user.setUsername(registerRequest.getUsername());
        user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
        user.setEmail(registerRequest.getEmail());
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());

        userMapper.insertUser(user); // Assumes insertUser sets the ID back to the user object if generated

        UserResponse response = new UserResponse();
        BeanUtils.copyProperties(user, response);
        return response;
    }

    @Override
    public UserResponse loginUser(UserLoginRequest loginRequest) {
        User user = userMapper.findByUsername(loginRequest.getUsername())
                .orElseThrow(() -> new ResourceNotFoundException("User not found with username: " + loginRequest.getUsername()));

        if (!passwordEncoder.matches(loginRequest.getPassword(), user.getPassword())) {
            throw new BadRequestException("Invalid username or password");
        }
        UserResponse response = new UserResponse();
//         if(user != null){
//             //生成jwt
//             Map<String,Object> claim = new HashMap<>();
//             Long id = user.getId();
//             String username = user.getUsername();
//             claim.put("id",id);
//             claim.put("username",username);
//             String jwtToken = Jwtutil.generateToken(claim);
//             user.setToken(jwtToken);
//         }

        BeanUtils.copyProperties(user, response);
        // In a real application, generate and return a JWT token here
        return response;
    }

    @Override
    public UserResponse getUserById(Long id) {
        User user = findUserEntityById(id);
        UserResponse response = new UserResponse();
        BeanUtils.copyProperties(user, response);
        return response;
    }

    @Override
    public User findUserEntityById(Long id) {
        return userMapper.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User not found with ID: " + id));
    }


    @Override
    @Transactional
    public UserResponse updateUser(Long id, UserUpdateRequest updateRequest) {
        User user = findUserEntityById(id);

        boolean updated = false;
        if (updateRequest.getEmail() != null && !updateRequest.getEmail().isEmpty() && !updateRequest.getEmail().equals(user.getEmail())) {
            // Check if new email is already taken by another user
            userMapper.findByEmail(updateRequest.getEmail()).ifPresent(existingUser -> {
                if (!existingUser.getId().equals(id)) {
                    throw new UserAlreadyExistsException("Email already taken: " + updateRequest.getEmail());
                }
            });
            user.setEmail(updateRequest.getEmail());
            updated = true;
        }

        if (updateRequest.getNewPassword() != null && !updateRequest.getNewPassword().isEmpty()) {
            user.setPassword(passwordEncoder.encode(updateRequest.getNewPassword()));
            updated = true;
        }

        if (updated) {
            user.setUpdatedAt(LocalDateTime.now());
            userMapper.updateUser(user);
        }

        UserResponse response = new UserResponse();
        BeanUtils.copyProperties(user, response);
        return response;
    }
}

